﻿namespace WatiN.Extensions
{
    using System;
    using System.Collections.Generic;

    using global::WatiN.Core;

#if MSTest
    using Microsoft.VisualStudio.TestTools.UnitTesting;
#endif
#if NUnit
    using NUnit.Framework;
#endif
#if Xunit
    using Xunit;
#endif

    using WatiN.Core.Constraints;

#if MSTest
    [TestClass]
#endif
#if NUnit
    [TestFixture]
#endif
    public abstract class WatiNTestBase
#if Xunit
        : IDisposable
#endif
    {
#if Xunit
        public WatiNTestBase()
        {
            this.CurrentBrowser = this.CreateBrowser();
        }

        public virtual void Dispose()
        {
            this.CurrentBrowser.Close();
            this.CurrentBrowser = null;
        }
#endif
        protected Browser CurrentBrowser { get; set; }

#if MSTest  
        [TestInitialize]
        public virtual void TestInitialize()
        {
            this.CurrentBrowser = this.CreateBrowser();
        }
        
        [TestCleanup]
        public virtual void TestCleanup()
        {
            this.CurrentBrowser.Close();
            this.CurrentBrowser = null;
        }
#endif
#if NUnit
        [SetUp]
        protected virtual void SetUp()
        {
            this.CurrentBrowser = this.CreateBrowser();
        }

        [TearDown]
        protected virtual void TearDown()
        {
            this.CurrentBrowser.Close();
            this.CurrentBrowser = null;
        }
#endif
        protected Browser CreateBrowser()
        {
            return this.CreateBrowser(Settings.DefaultBrowser);
        }

        protected Browser CreateBrowser(BrowserType browserType)
        {
            switch (browserType)
            {
                case BrowserType.IE:
                    return new IE(Settings.CreateIEInNewProcess);
                case BrowserType.FireFox:
                    return new FireFox();
            }

            throw new NotImplementedException();
        }

        protected void GoTo(string url)
        {
            this.CurrentBrowser.GoTo(url);
        }

        protected void GoTo(Uri uri)
        {
            this.CurrentBrowser.GoTo(uri);
        }

        /// <summary>
        /// Fires JS Event. Note: jQuery may be required to fire selected event.
        /// </summary>
        /// <typeparam name="TJSEvent">JS Event</typeparam>
        /// <param name="parameters">Event parameters</param>
        protected void FireJSEventByParameters<TJSEvent>(params string[] parameters) where TJSEvent : IJSEvent, new()
        {
            this.CurrentBrowser.FireJSEventByParameters<TJSEvent>(parameters);
        }

        /// <summary>
        /// Fires JS Event using Browser as a IElementContainer. Note: jQuery is required to fire selected event.
        /// </summary>
        /// <typeparam name="TJSEvent">JS Event</typeparam>
        /// <param name="elementId">ID of the element on which event will be fired</param>
        protected void FireJSEvent<TJSEvent>(string elementId) where TJSEvent : IJSEvent, new()
        {
            this.CurrentBrowser.FireJSEvent<TJSEvent>(elementId);
        }

        /// <summary>
        /// Fires JS Event using Browser as a IElementContainer. Note: jQuery is required to fire selected event.
        /// </summary>
        /// <typeparam name="TJSEvent">JS Event</typeparam>
        /// <param name="elementClass">Class of the element on which event will be fired</param>
        protected void FireJSEventByClass<TJSEvent>(string elementClass) where TJSEvent : IJSEvent, new()
        {
            this.CurrentBrowser.FireJSEventByClass<TJSEvent>(elementClass);
        }

        /// <summary>
        /// Gets TextField text using Browser as a IElementContainer
        /// </summary>
        /// <param name="constraint">Constraint by which TextField will be searched</param>
        /// <returns>TextField text</returns>
        protected string GetText(Constraint constraint)
        {
            return this.CurrentBrowser.GetText(constraint);
        }

        /// <summary>
        /// Gets TextField text using Browser as a IElementContainer
        /// </summary>
        /// <param name="textFieldIdOrNameOrValue">ID/Name/Value by which TextField will be searched</param>
        /// <returns>TextField text</returns>
        protected string GetText(string textFieldIdOrNameOrValue)
        {
            return this.CurrentBrowser.GetText(textFieldIdOrNameOrValue);
        }

        protected TElement Get<TElement>(Constraint constraint) where TElement : Element
        {
            return this.CurrentBrowser.Get<TElement>(constraint);
        }

        protected TElement Get<TElement>(Constraint constraint, bool assert) where TElement : Element
        {
            return this.CurrentBrowser.Get<TElement>(constraint, assert);
        }

        protected TElement Get<TElement>(string elementIdOrNameOrValue) where TElement : Element
        {
            return this.CurrentBrowser.Get<TElement>(elementIdOrNameOrValue);
        }

        protected TElement Get<TElement>(string elementIdOrNameOrValue, bool assert) where TElement : Element
        {
            return this.CurrentBrowser.Get<TElement>(elementIdOrNameOrValue, assert);
        }

        protected TElement GetByAttribute<TElement>(string elementAttributeName, string elementAttributeValue) where TElement : Element
        {
            return this.CurrentBrowser.GetByAttribute<TElement>(elementAttributeName, elementAttributeValue);
        }

        protected TElement GetByAttribute<TElement>(string elementAttributeName, string elementAttributeValue, bool assert) where TElement : Element
        {
            return this.CurrentBrowser.GetByAttribute<TElement>(elementAttributeName, elementAttributeValue, assert);
        }

        protected TElement GetByClass<TElement>(string elementClass) where TElement : Element
        {
            return this.CurrentBrowser.GetByClass<TElement>(elementClass);
        }

        protected TElement GetByClass<TElement>(string elementClass, bool assert) where TElement : Element
        {
            return this.CurrentBrowser.GetByClass<TElement>(elementClass, assert);
        }

        protected TElement GetByText<TElement>(string elementText) where TElement : Element
        {
            return this.CurrentBrowser.GetByText<TElement>(elementText);
        }

        protected TElement GetByText<TElement>(string elementText, bool assert) where TElement : Element
        {
            return this.CurrentBrowser.GetByText<TElement>(elementText, assert);
        }

        protected TElement GetByUrl<TElement>(string elementUrl) where TElement : Element
        {
            return this.CurrentBrowser.GetByUrl<TElement>(elementUrl);
        }

        protected TElement GetByUrl<TElement>(string elementUrl, bool assert) where TElement : Element
        {
            return this.CurrentBrowser.GetByUrl<TElement>(elementUrl, assert);
        }

        protected TElement GetByUrl<TElement>(Uri uri) where TElement : Element
        {
            return this.CurrentBrowser.GetByUrl<TElement>(uri);
        }

        protected TElement GetByUrl<TElement>(Uri uri, bool assert) where TElement : Element
        {
            return this.CurrentBrowser.GetByUrl<TElement>(uri, assert);
        }

        protected IList<TElement> GetAll<TElement>(string elementIdOrNameOrValue) where TElement : Element
        {
            return this.CurrentBrowser.GetAll<TElement>(elementIdOrNameOrValue);
        }

        protected IList<TElement> GetAll<TElement>(Constraint constraint) where TElement : Element
        {
            return this.CurrentBrowser.GetAll<TElement>(constraint);
        }

        protected IList<TElement> GetAllByAttribute<TElement>(string elementAttributeName, string elementAttributeValue) where TElement : Element
        {
            return this.CurrentBrowser.GetAllByAttribute<TElement>(elementAttributeName, elementAttributeValue);
        }

        protected IList<TElement> GetAllByClass<TElement>(string elementClass) where TElement : Element
        {
            return this.CurrentBrowser.GetAllByClass<TElement>(elementClass);
        }

        protected IList<TElement> GetAllByText<TElement>(string elementText) where TElement : Element
        {
            return this.CurrentBrowser.GetAllByText<TElement>(elementText);
        }

        protected IList<TElement> GetAllByUrl<TElement>(Uri elementUri) where TElement : Element
        {
            return this.CurrentBrowser.GetAllByUrl<TElement>(elementUri);
        }

        protected IList<TElement> GetAllByUrl<TElement>(string elementUrl) where TElement : Element
        {
            return this.CurrentBrowser.GetAllByUrl<TElement>(elementUrl);
        }

        protected void Click<TElement>(Constraint constraint) where TElement : Element
        {
            this.CurrentBrowser.Click<TElement>(constraint);
        }

        protected void Click<TElement>(Constraint constraint, bool assert) where TElement : Element
        {
            this.CurrentBrowser.Click<TElement>(constraint, assert);
        }

        protected void Click<TElement>(string elementIdOrNameOrValue) where TElement : Element
        {
            this.CurrentBrowser.Click<TElement>(elementIdOrNameOrValue);
        }

        protected void Click<TElement>(string elementIdOrNameOrValue, bool assert) where TElement : Element
        {
            this.CurrentBrowser.Click<TElement>(elementIdOrNameOrValue, assert);
        }

        protected void ClickByClass<TElement>(string elementClass) where TElement : Element
        {
            this.CurrentBrowser.ClickByClass<TElement>(elementClass);
        }

        protected void ClickByClass<TElement>(string elementClass, bool assert) where TElement : Element
        {
            this.CurrentBrowser.ClickByClass<TElement>(elementClass, assert);
        }

        protected void ClickByText<TElement>(string elementText) where TElement : Element
        {
            this.CurrentBrowser.ClickByText<TElement>(elementText);
        }

        protected void ClickByText<TElement>(string elementText, bool assert) where TElement : Element
        {
            this.CurrentBrowser.ClickByText<TElement>(elementText, assert);
        }

        protected void ClickByUrl<TElement>(string url) where TElement : Element
        {
            this.CurrentBrowser.ClickByUrl<TElement>(url);
        }

        protected void ClickByUrl<TElement>(string url, bool assert) where TElement : Element
        {
            this.CurrentBrowser.ClickByUrl<TElement>(url, assert);
        }

        protected void ClickByUrl<TElement>(Uri uri) where TElement : Element
        {
            this.CurrentBrowser.ClickByUrl<TElement>(uri);
        }

        protected void ClickByUrl<TElement>(Uri uri, bool assert) where TElement : Element
        {
            this.CurrentBrowser.ClickByUrl<TElement>(uri, assert);
        }

        protected void SetText(Constraint constraint, string text, bool append = false)
        {
            this.CurrentBrowser.SetText(constraint, text, append);
        }

        protected void SetText(string textFieldIdOrNameOrValue, string text, bool append = false)
        {
            this.CurrentBrowser.SetText(textFieldIdOrNameOrValue, text, append);
        }

        protected void SetTextByClass(string textFieldClass, string text, bool append = false)
        {
            this.CurrentBrowser.SetTextByClass(textFieldClass, text, append);
        }

        protected void SetTextByText(string textFieldText, string text, bool append = false)
        {
            this.CurrentBrowser.SetTextByText(textFieldText, text, append);
        }

        protected void TypeText(Constraint constraint, string text, bool append = false)
        {
            this.CurrentBrowser.TypeText(constraint, text, append);
        }

        protected void TypeText(string textFieldIdOrNameOrValue, string text, bool append = false)
        {
            this.CurrentBrowser.TypeText(textFieldIdOrNameOrValue, text, append);
        }

        protected void SelectValue(Constraint constraint, string value)
        {
            this.CurrentBrowser.SelectValue(constraint, value);
        }

        protected void SelectValue(string selectListIdOrNameOrValue, string value)
        {
            this.CurrentBrowser.SelectValue(selectListIdOrNameOrValue, value);
        }

        protected void SelectValueByText(Constraint constraint, string text)
        {
            this.CurrentBrowser.SelectValueByText(constraint, text);
        }

        protected void SelectValueByText(string selectListIdOrNameOrValue, string text)
        {
            this.CurrentBrowser.SelectValueByText(selectListIdOrNameOrValue, text);
        }

        protected void Check(string checkBoxIdOrNameOrValue, bool check = true)
        {
            this.CurrentBrowser.Check(checkBoxIdOrNameOrValue, check);
        }

        protected void Check(Constraint constraint, bool check = true)
        {
            this.CurrentBrowser.Check(constraint, check);
        }

        protected void CheckByClass(string checkBoxClass, bool check = true)
        {
            this.CurrentBrowser.CheckByClass(checkBoxClass, check);
        }

        protected void SetTextUsingJS(string textFieldId, string text)
        {
            this.CurrentBrowser.SetTextUsingJS(textFieldId, text);
        }

        protected void SetTextByClassUsingJS(string textFieldClass, string text)
        {
            this.CurrentBrowser.SetTextByClassUsingJS(textFieldClass, text);
        }
    }
}
